/*
 * ChessGame.cpp
 *
 *  Created on: Mar 8, 2011
 *      Author: Michael Ziminsky
 */

#include "ChessGame.h"
#include "model/pieces/King.h"
#include "ChessMove.h"

ChessGame::ChessGame() : gui(*this, gameBoard) {}

bool ChessGame::isLightTurn() const
{
    return gameBoard.isLightTurn();
}

bool ChessGame::attemptMove(MovePiece& move)
{
    bool valid = true;
    globals::cPiece p = gameBoard.getPieceAt(move.from);
    if (p && (p->isLight == gameBoard.isLightTurn() && getValidMoves(p, NULL)->count(move) > 0))
    {
        move.execute(gameBoard);
        gameBoard.switchTurn();
    }
    else valid = false;
    return valid;
}

void ChessGame::newGame()
{
    gameBoard.clear();
    ChessMove(startBoard).execute(gameBoard);
}

globals::moveSet ChessGame::getValidMoves(const globals::cPiece& pc, model::ChessBoard* b) const
{
    globals::moveSet moves;
    if (pc)
    {
        bool dynamic;
        if ((dynamic = (!b || b == &gameBoard)))
            b = new model::ChessBoard(gameBoard);
        moves = pc->getPotentialMoves(*b);
        bool turn = b->isLightTurn();
        for (globals::moveSet::element_type::const_iterator i = moves->begin(); i != moves->end(); i++)
        {
            ((MovePiece)*i).execute(*b);
            if (inCheck(turn, b)) moves->erase(i);
            ((MovePiece)*i).undo(*b);
        }
        if (dynamic) delete b;
    }
    return moves;
}

const model::ChessBoard& ChessGame::getBoard() const
{
    return gameBoard;
}

bool ChessGame::inCheck(bool light,const model::ChessBoard* b) const
{
    bool dynamic, check = false;
    if ((dynamic = (!b || b == &gameBoard)))
        b = new model::ChessBoard(gameBoard);
    const model::Location* kl = b->getKing(light)->getLocation();
    globals::pieceList use(b->getPieces(!light));
    for (globals::pieceList::element_type::const_iterator i = use->begin(); !check && i != use->end(); i++)
    {
        globals::moveSet moves((*i)->getPotentialMoves(*b));
        for (globals::moveSet::element_type::const_iterator m = moves->begin(); m != moves->end(); m++)
            if ((check = (m->to == *kl))) break;
    }
    if (dynamic) delete b;
    return check;
}

bool ChessGame::inCheckMate(bool light, model::ChessBoard* b) const
{
    bool dynamic, checkmate = true;
    if ((dynamic = (!b || b == &gameBoard)))
        b = new model::ChessBoard(gameBoard);
    globals::pieceList use(b->getPieces(light));
    for (globals::pieceList::element_type::const_iterator i = use->begin(); i != use->end(); i++)
        if (!(checkmate = !(getValidMoves(*i, b)->size() > 0))) break;
    if (dynamic) delete b;
    return checkmate;
}

void ChessGame::showGUI(bool show)
{
    if (show)
        gui.show();
    else
        gui.hide();
}

const std::string ChessGame::startBoard("RlA1 NlB1 BlC1 QlD1 KlE1 BlF1 NlG1 RlH1 "
                                        "PlA2 PlB2 PlC2 PlD2 PlE2 PlF2 PlG2 PlH2 "
                                        "PdA7 PdB7 PdC7 PdD7 PdE7 PdF7 PdG7 PdH7 "
                                        "RdA8 NdB8 BdC8 QdD8 KdE8 BdF8 NdG8 RdH8");
